const {
	getMSTime,
} = require('../index')
const _DateUtils = require('../dateUtils')
const _DBMongo = require('../db-mongo')
const _CrawlerMongo = require('../config/CrawlerMongo')
const _mongo = new _CrawlerMongo()
const _colName = 'task'
const _instance = {
	__params: {}
}

module.exports = class Task {
	constructor(task_name, _type_) {
		this.__isCreated = false
		_instance.__params = {}
		if (typeof task_name == 'object') {
			this.__init(task_name)
			return this
		}
		this.task_name = task_name
		if (_type_ && _type_.id)
			this._type_ = _type_
		else
			this._type_ = {
				id: _type_,
				name: _type_,
			}
	}

	__init(options) {
		Object.assign(this, options)
	}

	create(options) {
		return create.call(this, options)
	}

	setParams(k, v) {
		if (typeof k == 'object') {
			Object.assign(_instance.__params, k)
			return this
		}
		_instance.__params[k] = v
		return this
	}

	update(params) {
		if (!this._id)
			throw new Error('---Task not init!!!!---')
		params._stop = null
		return updateThis.call(this, params)
	}

	flush() {
		if (!this._id)
			throw new Error('---Task not init!!!!---')
		_instance.__params = {}
		return findById.call(this)
	}

	stop(params) {
		if (!this._id)
			throw new Error('---Task not init!!!!---')
		if (typeof params == 'string') {
			try {
				params = JSON.parse(params)
			} catch (e) {
				params = null
			}
		}
		params = params && typeof params == 'object' ? params : {}
		return updateThis.call(this, {
			pid: -1,
			status: 2,
			_stop: params,
		})
	}

	done() {
		if (!this._id)
			throw new Error('---Task not init!!!!---')
		return updateThis.call(this, {
			pid: -1,
			status: -1,
			_stop: null,
		})
	}

	static updateOne(filter, update) {
		return updateTaskStatic(filter, update, 'updateOne')
	}

	static updateMany(filter, update) {
		return updateTaskStatic(filter, update, 'updateMany')
	}

	static findOneAndUpdate(filter, update) {
		return updateTaskStatic(filter, update, 'findOneAndUpdate')
	}

	static findOne(filter) {
		return findOneStatic(filter)
	}

	static deleteMany(filter) {
		return deleteManyStatic(filter)
	}

}

/**
 * 更新任务
 * @param  {[type]} params [description]
 * @return {[type]}        [description]
 */
async function updateThis(params) {
	params = params && typeof params == 'object' ? params : {}
	delete params._id
	Object.assign(_instance.__params, params)
	_instance.__params.modify_time = getMSTime()
	if (params.status == -1 || params.status == 2) {
		_instance.__params.duration = _DateUtils.durationTime(Date.now() - new Date(this.start_time))
	}
	let collection = await _mongo.getCollection(_colName)
	return collection.updateOne({
		_id: this._id,
		status: {
			$ne: -1
		}
	}, {
		$set: _instance.__params
	})
}

/**
 * 新建任务
 * @param  {[type]} options [description]
 * @return {[type]}         [description]
 */
async function create(options) {
	options = options && typeof options == 'object' ? options : {}
	let task = {
		task_id: Date.now(),
		task_name: this.task_name,
		_type_: this._type_,
	}
	Object.assign(task, options)
	let collection = await _mongo.getCollection(_colName)
	let result = await collection.insertOne(task)
	this._id = result.insertedId
	return result
}

/**
 * 更新任务
 * @param  {[type]} filter [description]
 * @param  {[type]} update [description]
 * @param  {[type]} type   [description]
 * @return {[type]}        [description]
 */
async function updateTaskStatic(filter, update, type) {
	filterObjectId(filter)
	delete update._id
	let collection = await _mongo.getCollection(_colName)
	return collection[type](filter, {
		$set: update
	})
}

/**
 * 查找
 * @return {[type]} [description]
 */
async function findById() {
	let collection = await _mongo.getCollection(_colName)
	let task = await collection.findOne({
		_id: this._id
	})
	Object.assign(this, task)
	return this
}

async function findOneStatic(query) {
	filterObjectId(query)
	let collection = await _mongo.getCollection(_colName)
	return collection.findOne(query)
}

async function deleteManyStatic(filter) {
	filterObjectId(filter)
	let collection = await _mongo.getCollection(_colName)
	return collection.deleteMany(filter)
}

function filterObjectId(params) {
	if (params && params._id) {
		params._id = _DBMongo.ObjectID(params._id)
	}
	return params
}